﻿
/* Copyright 2009 we | Software Company.
 * 
 * This file is part of "we | moonlight".
 * 
 * we | moonlight is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License Version 3 as published by the 
 * Free Software Foundation.
 * 
 * we | moonlight is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with we | moonlight. 
 * If not, see http://www.gnu.org/licenses/.
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

using We.Moonlight.IndependentDrawing;
using We.Moonlight.Geometry;
using We.Moonlight.MSql;
using We.Moonlight.ViDesk;
using We.Moonlight.ViItem;

namespace We.Moonlight
{
    public partial class Form1 : Form
    {
        #region Confiruration

        //Flip Timer, Ticks each Frame
        public static Timer FlipTimer = new Timer ( ) { Interval = (int)Math.Round ((1000.0d / 30.0d), 0) };
        //List of all desks
        private List<PassiveDesk> Desks = new List<PassiveDesk> ( );
        //the Currently Active Desk
        private ActiveDesk CurrentDesk;
        //teh Active IVi
        private IVi Current;
        //the Clipboarded IVi
        private IVi Clip;
        //How to draw
        public System.Drawing.Drawing2D.SmoothingMode mySmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        //how to draw the background Image
        public We.Moonlight.Layout BackgroundImageMode = We.Moonlight.Layout.Stretch;
        //the Background Image
        private Bitmap Background = Properties.Resources.img24;

        #endregion
        #region Constructors and Initialization

        public Form1 ( )
        {
            FileAssoc.Fill ( );

            InitializeComponent ( );
            Initialize ( );
            InitializeDesks ( );

            this.DoubleBuffered = true;

            ChangeBackgroundDrawingMode (Moonlight.Layout.FitVertically);
            this.Size = Screen.FromControl (this).Bounds.Size;
            this.Location = new Point (0, 0);

            DrawBackground (ref BackgroundDrawing);
            DrawInactiveItems (ref ItemsDrawing);

            
        }
        private void Initialize ( )
        {
            this.Paint += new PaintEventHandler (Draw);
            this.MouseUp += new System.Windows.Forms.MouseEventHandler (this.hMouseUp);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler (this.hMouseDown);
            this.MouseMove += new System.Windows.Forms.MouseEventHandler (this.hMouseMove);
            this.Resize += new EventHandler (Form1_Resize);
            this.FormClosing += new FormClosingEventHandler (Form1_FormClosing);
            button1.MouseEnter += new EventHandler(button1_MouseHover);
            button2.MouseEnter += new EventHandler(button2_MouseHover);
            button3.MouseEnter += new EventHandler(button3_MouseHover);
            button4.MouseEnter += new EventHandler(button4_MouseHover);
            button5.MouseEnter += new EventHandler(button5_MouseHover);
            button1.Click += new EventHandler(button1_Click);
            button2.Click += new EventHandler(button2_Click);
            button3.Click += new EventHandler(button3_Click);
            button4.Click += new EventHandler(button4_Click);
            button5.Click += new EventHandler(button5_Click);
            button1.MouseLeave += new EventHandler(button_MouseLeave);
            button2.MouseLeave += new EventHandler (button_MouseLeave);
            button3.MouseLeave += new EventHandler(button_MouseLeave);
            button4.MouseLeave += new EventHandler(button_MouseLeave);
            button5.MouseLeave += new EventHandler (button_MouseLeave);
        }
        private void InitializeDesks ( )
        {
            //Fill Desk List
            Desks = SqlViDesk.Select ( );

            if (Desks == null)
            {
                //no desks!
                btnNextDesk.Enabled = false;
                btnPrevDesk.Enabled = false;
                btnDesk.Enabled = false;

                btnDesk.Text = "Desks";
                btnDesk.Image = Properties.Resources.application;
                this.BackColor = Color.Black;

                return;
            }
            foreach (PassiveDesk d in Desks)
            {
                ToolStripMenuItem TMI = new System.Windows.Forms.ToolStripMenuItem ( );
                try { TMI.Image = Image.FromFile (d.Icon.FullName); }
                catch (NullReferenceException) { TMI.Image = global::We.Moonlight.Properties.Resources.application; }
                TMI.Text = d.Name;
                TMI.Click += new EventHandler (TMI_Click);
                this.btnDesk.DropDownItems.Add (TMI);
            }
            if (Desks.Count > 1)
            {
                btnNextDesk.Enabled = true;
                btnPrevDesk.Enabled = true;
                btnDesk.Enabled = true;
            }
            this.BackColor = Color.Black;

            btnDesk.Text = "Desks";
            btnDesk.Image = Properties.Resources.application;

            if (Desks.Where (n => n.ID == Properties.Settings.Default.DefaultDeskID).Any ( ))
            {
                ChangeDesk (Desks.Where (n => n.ID == Properties.Settings.Default.DefaultDeskID).FirstOrDefault ( ));
            }
        }

        #endregion

        #region Drawing

        private Bitmap BackgroundDrawing;
        private Bitmap ItemsDrawing;

        private BackgroundDrawingHandler BackgroundDrawingDelegate;

        public BackgroundDrawingHandler BackgroundDrawingDlgt
        {
            get { return BackgroundDrawingDelegate; }
        }

        public void ChangeBackgroundDrawingMode (Layout L)
        {
            BackgroundDrawingDelegate = L.ToBackgroundDrawingHandler ( );
            DrawBackground (ref BackgroundDrawing);
            Invalidate ( );
        }

        private void DrawInactiveItems (ref Graphics G)
        {
            G.Clear(Color.FromArgb(0,0,0,0));
            //Tio avoid nullRefeences, check first
            if (CurrentDesk != null)
            {
                //dont draw the current IVi, it will be drawn in the paint routine.
                foreach (IVi Vi in CurrentDesk.Documents.Where (n => !n.Equals (Current)).OrderByDescending (n => n.Layer))
                {
                    //have each IVi draw itself the way it wants.
                    Vi.Draw (ref G);
                }
            }
            //if there istnt a desk selected, nothing needs to be drawn.
        }
        private void DrawInactiveItems (ref Bitmap B)
        {
            if (ItemsDrawing == null)
                ItemsDrawing = new Bitmap (this.ClientRectangle.Size.Width, this.ClientRectangle.Size.Height);

            Graphics g = Graphics.FromImage (B);
            DrawInactiveItems (ref g);
            g.Dispose ( ); g = null;
        }
        private void DrawBackground (ref Graphics G)
        {
            //if a Background Drawing mode has been specified, us it
            if (BackgroundDrawingDelegate != null)
            {
                G.Clear (this.BackColor);
                BackgroundDrawingDelegate.Invoke (ref G, ref Background, BackgroundDrawing.Size);
            }
            //otherwise Fill tha Background with the Back Color
            else
                G.Clear (this.BackColor);
        }
        private void DrawBackground (ref Bitmap B)
        {
            if (BackgroundDrawing == null)
                BackgroundDrawing = new Bitmap (this.ClientRectangle.Size.Width, this.ClientRectangle.Size.Height);
            Graphics g = Graphics.FromImage (B);
            DrawBackground (ref g);
            g.Dispose ( ); g = null;
        }
        private void Draw (object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            g.SmoothingMode = mySmoothingMode;
            //choose this by the number of ViDocs?

            // draw the Background image at the very Bottom
            g.DrawImage (BackgroundDrawing, new Point (0, 0));
            // all Inactive IVis on top of that
            g.DrawImage (ItemsDrawing, new Point (0, 0));
            //and the Current IVi/the temporyry IVi Preview at the very top.
            if (Current != null)
            {
                Current.Draw (ref g);
            }
            if (pointing)
            {
                g.DrawImage(ViDoc.Sample.Bmp, ViDoc.Sample.Corners);
            }

        }

        #endregion

        #region GUI Events

        private void appearanceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadBackgroundChanger();
        }
        private void toolStripButton1_Click (object sender, EventArgs e)
        {
            pointing = true;
            toolStripButton1.Enabled = false;
            Current = null;
        }
        private void toolStripButton2_Click (object sender, EventArgs e)
        {
            TurnOff ( );
        }
        void Form1_Resize (object sender, EventArgs e)
        {
            if (CurrentDesk != null)
            {
                BackgroundDrawing = new Bitmap (this.ClientRectangle.Size.Width, this.ClientRectangle.Size.Height);
                DrawBackground (ref BackgroundDrawing);
            }
        }
        void Form1_FormClosing (object sender, FormClosingEventArgs e)
        {
            SaveDeskState ( );
        }

        #endregion
        #region Transformation Handlers

        private bool dragging, rotating, scaling, pointing, flipping;
        private bool transformed;
        private double bDist;
        private Point _pt;

        private IVi ViDocFromPoint (Point PT)
        {
            IEnumerable<IVi> CouldBe =
                CurrentDesk.Documents.Where (n => n.isOn (PT))
                .OrderBy (n => n.Layer)
                ;

            if (CouldBe.Any ( ))
            {
                Current = CouldBe.FirstOrDefault ( );
                foreach (IVi D in CurrentDesk.Documents.Where (n => n.Layer < CouldBe.FirstOrDefault ( ).Layer))
                {
                    D.Layer++;
                }
                CouldBe.FirstOrDefault ( ).Layer = 0;
                return CouldBe.FirstOrDefault ( );
            }
            else
            {
                return null;
            }

        }

        private void hMouseDown (object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (pointing)
            {
                pointing = false;
                transformed = true;
                toolStripButton1.Enabled = true;
                foreach (ViDoc d in CurrentDesk.Documents)
                { d.Layer++; }
                AddViDoc();
                Invalidate ( );
                return;
            }


            Current = ViDocFromPoint (e.Location);
            if (Current == null) return;

            DrawInactiveItems (ref ItemsDrawing);

            if (!rotating && !dragging && !pointing && !scaling && !flipping)
            {
                if (e.Button == MouseButtons.Left) dragging = true;
                else if (e.Button == MouseButtons.Right) rotating = true;
                else if (e.Button == MouseButtons.Middle) { scaling = true; bDist = Delta.DistanceBetween(e.Location, Current.Location); }
                _pt = e.Location;
            }
            Invalidate ( );
        }
        private void hMouseMove (object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (!rotating && !dragging && !pointing && !scaling && !flipping)
            {
                if (e.Location.Y <= 25)
                {
                    if (!toolStrip1.Visible)
                    {
                        toolStrip1.Visible = true;
                        toolStrip1.Location = new Point (e.X - 20, 0);
                    }
                }
                else toolStrip1.Visible = false;

                if (e.Location.Y >= this.ClientRectangle.Height - 25)
                {
                    if (!toolStrip2.Visible)
                    {
                        toolStrip2.Visible = true;
                        toolStrip2.Location = new Point (e.X - 20, this.ClientRectangle.Height - 25);
                    }
                }
                else toolStrip2.Visible = false;
            }

            if (pointing)
            {
                ViDoc.Sample.Translate (e.Location.X, e.Location.Y, true);
                return;
            }

            if (!dragging && !rotating && !scaling)
                return;
            else if (dragging)
                Current.Translate(e.Location.X - _pt.X, e.Location.Y - _pt.Y, false);
            else if (rotating)
                Current.Rotate(Delta.AngleBetween(_pt, e.Location, Current.Location), false);
            else if (scaling)
            {
                Current.Scale(Delta.DistanceBetween(e.Location, Current.Location) / bDist, false);
                bDist = Delta.DistanceBetween(e.Location, Current.Location);
            }
            _pt = e.Location;
            transformed = true;
            this.ContextMenuStrip = null;
            Invalidate ( );
        }
        private void hMouseUp (object sender, System.Windows.Forms.MouseEventArgs e)
        {
            pointing = dragging = rotating = scaling = false;
            if (!transformed && Current != null)
            {
                Current.Clicked (e.Button);
                Invalidate ( );
                //clicked
            }
            transformed = false;
            Current = null;
            DrawInactiveItems (ref ItemsDrawing);
            ContextMenuStrip = contextMenuStrip1;
        }

        #endregion

        #region Desk Management

        private void ChangeDesk (PassiveDesk P)
        {
            SaveDeskState ( );
            CurrentDesk = P.Activate ( );
            this.BackColor = Color.DimGray;
            btnDesk.Text = CurrentDesk.Name;
            btnDesk.Image = CurrentDesk.Icon;
            DrawBackground(ref BackgroundDrawing);
            DrawInactiveItems(ref ItemsDrawing);
            Invalidate ( );
        }
        private void SaveDeskState ( )
        {
            if (CurrentDesk != null)
            {
                foreach (IVi VD in CurrentDesk.Documents)
                {
                    VD.Update ( );
                }
            }
        }
        void TMI_Click (object sender, EventArgs e)
        {
            //sender.ToString() = the name of the desk
            ChangeDesk (Desks.Where (n => n.Name == sender.ToString ( )).FirstOrDefault ( ));
        }

        #endregion
        #region ViDoc Management

        private void AddViDoc ( )
        {

            if (CurrentDesk.Documents.Count > 50)
                mySmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            else
                mySmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        }

        private void TurnOff ( )
        {
            Application.Exit ( );

        }

        #endregion

        #region Background Layout

        private bool backchangerloaded = false;
        private void LoadBackgroundChanger ( )
        {
            if (backchangerloaded) return;
            Prev = BackgroundDrawingDlgt.ToLayout ( );
            panel1.Visible = true;
            panel1.Location = new Point ((ClientRectangle.Width - panel1.Width) / 2, (ClientRectangle.Height - panel1.Height) / 2);
            backchangerloaded = true;
        }

        private Layout Prev;
        void button_MouseLeave (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Prev);
        }

        void button5_MouseHover (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.FitVertically);
        }
        void button4_MouseHover (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.FitHorizontally);
        }
        void button3_MouseHover (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.Center);
        }
        void button2_MouseHover (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.Tile);
        }
        void button1_MouseHover (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.Stretch);
        }

        private void button1_Click (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.Stretch);
            Prev = Moonlight.Layout.Stretch;
            panel1.Hide ( );
            backchangerloaded = false;
        }
        private void button2_Click (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.Tile);
            Prev = Moonlight.Layout.Tile;
            panel1.Hide ( );
            backchangerloaded = false;
        }
        private void button3_Click (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.Center);
            Prev = Moonlight.Layout.Center;
            panel1.Hide ( );
            backchangerloaded = false;
        }
        private void button4_Click (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.FitHorizontally);
            Prev = Moonlight.Layout.FitHorizontally;
            panel1.Hide ( ); backchangerloaded = false;
        }
        private void button5_Click (object sender, EventArgs e)
        {
            ChangeBackgroundDrawingMode (Moonlight.Layout.FitVertically);
            Prev = Moonlight.Layout.FitVertically;
            panel1.Hide ( ); backchangerloaded = false;
        }

        #endregion

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}
